/**
  * 16.4 类型投影
  * 先回顾一下 java 的内部类
  *
  * class Outter{
  * public class Inner {}
  * public void foo(Inner c){
  *     System.out.println(c);
  * }
  * }
  * public class Main {
  * public static void main(String[] args)throws Exception{
  * Outter o1 = new Outter();
  * Outter o2 = new Outter();
  *     Outter.Inner i1 = o1.new Inner();
  *     Outter.Inner i2 = o2.new Inner();
  * o1.foo(i2);
  * }
  * }
  *
  * 上面在 Outter 类内部定义了 Inner 类，在后边 main 里创建了两个 Inner
  * 实例，注意创建内部类的时候
  * Outter.Inner i1 = o1.new Inner();
  * 在用 new 创建内部类时，前边必须限定外部对象(内部类实例必须要访问
  * 到外部对象引用)： o1；如果是在 Outter 类内部这个外部引用可以省略，它默
  * 认会用传递外部 this 引用
  */
//同样的事情翻译为 scala 代码：
class A {
  class B;
  def foo(b:B) = println(b)
}
val a1 = new A
val a2 = new A
val b1 = new a1.B
val b2 = new a2.B

/**
  * 在创建内部类的时候，语法上与 java 有所不同，不是 outter.new
  * Inner() 而是 new outter.Inner()，看上去只是表象不同么？实际上， scala 有很
  * 大差异，不同于 java 里 i1 和 i2 类型是相同的，否则 o1.foo(i2) 就不能执行
  * 了， scala 里的 b1 和 b2 是不同的类型：
  */


/**
scala> a1.foo(b2)
<console>:12: error: type mismatch;
found : a2.B
required: a1.B
按照方法的提示: a1.foo 方法接受的参数类型为： a1.B，而传入的 b2 类
型是 a2.B，两者不匹配。验证一下：
scala> typeOf[a1.B] == typeOf[a2.B]
res2: Boolean = false
确实是不一样的类型，它跟外部的实例相关，那个 foo 方法参数类型 B
的写法是缩写，省略了路径：
def foo(b: B) // 相当于 this.B 或 A.this.B
这里要引入一个概念：路径依赖类型；比如上面的 A.this.B 就是一个路
径依赖类型， B 前面的路径 A.this 随着不同的实例而不同，比如 a1 和 a2
就是两个不同的路径，所以 a1.B 与 a2.B 也是不同的类型。路径依赖类型的路
径完整写法：
1) 内部类定义在 object 里面，路径： package.object.Inner
  */
//object Singleton {
//  class Inner
//}
//val x = new p1.p2.p3.Singleton.Inner